package com.tian.controller;

import com.alibaba.fastjson.JSON;
import com.tian.constant.RabbitMQConstant;
import com.tian.entity.ChargeUser;
import com.tian.enums.UserBalanceChangeTypeEnum;
import com.tian.factory.ApplicationContextFactory;
import com.tian.mapper.ChargeUserMapper;
import com.tian.message.UserBalanceIncrMessage;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.UUID;

/**
 * {@code @description:} TODO
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-03-24 10:17
 * {@code @version:} 1.0
 */
@Slf4j
@Scope("prototype")
@RestController
public class TestController {
//    @Resource
//    RabbitTemplate rabbitTemplate;
    @Resource
    ChargeUserMapper chargeUserMapper;
    @Resource
    private RedissonClient redissonClient;

    @GetMapping("/")
    public String userBalanceIncr() {
        UserBalanceIncrMessage userBalanceIncrMessage = new UserBalanceIncrMessage();
        userBalanceIncrMessage.setUserId(1L);
        userBalanceIncrMessage.setChangeBalance(new BigDecimal(100));
        userBalanceIncrMessage.setChangeType(UserBalanceChangeTypeEnum.USER_RECHARGE.getType());
        userBalanceIncrMessage.setRemark(UserBalanceChangeTypeEnum.USER_RECHARGE.getDesc());
        //订单号
        userBalanceIncrMessage.setReqId("10001");

        sendMessage(JSON.toJSONString(userBalanceIncrMessage), RabbitMQConstant.USER_BALANCE_INCREASE_EXCHANGE,
                RabbitMQConstant.USER_BALANCE_INCREASE_ROUTING_KEY);
        return "test ok";
    }

    public void sendMessage(String message, String mqExchange, String mqRoutingKey) {
        log.info("send msg={}", message);
        RabbitTemplate rabbitTemplate = ApplicationContextFactory.getBean(RabbitTemplate.class);
        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("UserPointConfirm ConfirmCallback 关联数据：{},投递成功,确认情况：{}", correlationData, ack);
            } else {
                // TODO: 2024-11-26 这里可以重试 比如临时表+定时任务 继续补偿发送
                log.info("UserPointConfirm ConfirmCallback 关联数据：{},投递失败,确认情况：{}，原因：{}", correlationData, ack, cause);
            }
        });

        rabbitTemplate.setReturnCallback((msg, replyCode, replyText, exchange, routingKey) -> {
            log.info("UserPointConfirm ReturnsCallback 消息：{},回应码：{},回应信息：{},交换机：{},路由键：{}"
                    , msg, replyCode
                    , replyText, exchange
                    , routingKey);
        });
        rabbitTemplate.convertAndSend(mqExchange
                , mqRoutingKey, message, message1 -> {
                    message1.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 设置消息持久化
                    return message1;
                }, correlationId);
    }
    @GetMapping("/push")
    public String push() {
        for (int i = 1; i <= 5; i++) {
            //这个参数是用来做消息的唯一标识
            //发布消息时使用，存储在消息的headers中
            ChargeUser user = chargeUserMapper.selectByPrimaryKey(1L);


            // 关联的数据，可以用在消息投递失败的时候，作为一个线索，比如我把当前用户的id放进去，如果user消息投递失败
            // 我后面可以根据id再找到user，再次投递数据
//            CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString().concat("-") + i);
//            if (i == 2) {
//                //故意把交换机写错，演示 confirmCallback
//                rabbitTemplate.convertAndSend("TestDirectExchange_111", "TestDirectRouting",
//                        JSON.toJSONString(user), correlationData);
//            } else if (i == 3) {
//                //故意把路由键写错，演示 returnCallback
//                rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting_111",
//                        JSON.toJSONString(user), correlationData);
//            } else {
//                //正常发送
//                rabbitTemplate.convertAndSend(RabbitMQConstant.USER_BALANCE_INCREASE_EXCHANGE,
//                        RabbitMQConstant.USER_BALANCE_INCREASE_ROUTING_KEY,
//                        JSON.toJSONString(user), correlationData);
//            }
        }
        return "producer push ok";
    }
}
